import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Lexer {
    // 定义词法规则
    private static final Pattern NUMBER_PATTERN = Pattern.compile("\\d+");
    private static final Pattern OPERATOR_PATTERN = Pattern.compile("[-+*/]");
    private static final Pattern LPAREN_PATTERN = Pattern.compile("\\(");
    private static final Pattern RPAREN_PATTERN = Pattern.compile("\\)");

    public List<Token> lex(String expression) {
        List<Token> tokens = new ArrayList<>();
        while (!expression.isEmpty()) {
            Matcher matcher = null;
            if ((matcher = NUMBER_PATTERN.matcher(expression)).lookingAt()) {
                String value = matcher.group();
                tokens.add(new Token(TokenType.NUMBER, value));
            } else if ((matcher = OPERATOR_PATTERN.matcher(expression)).lookingAt()) {
                String value = matcher.group();
                tokens.add(new Token(TokenType.OPERATOR, value));
            } else if ((matcher = LPAREN_PATTERN.matcher(expression)).lookingAt()) {
                String value = matcher.group();
                tokens.add(new Token(TokenType.LPAREN, value));
            } else if ((matcher = RPAREN_PATTERN.matcher(expression)).lookingAt()) {
                String value = matcher.group();
                tokens.add(new Token(TokenType.RPAREN, value));
            } else {
                throw new RuntimeException("Invalid token: " + expression.charAt(0));
            }
            expression = expression.substring(matcher.end());
        }
        return tokens;
    }

    public static void main(String[] args) {
        String expression = "(3+4)*2";
        Lexer lexer = new Lexer();
        List<Token> tokens = lexer.lex(expression);
        for (Token token : tokens) {
            System.out.printf("Token: %s, Type: %s\n", token.getValue(), token.getType());
        }
    }
}

enum TokenType {
    NUMBER, OPERATOR, LPAREN, RPAREN
}

class Token {
    private final TokenType type;
    private final String value;

    public Token(TokenType type, String value) {
        this.type = type;
        this.value = value;
    }

    public TokenType getType() {
        return type;
    }

    public String getValue() {
        return value;
    }
}
